#include "HTMLGenerator.h"


HTMLGenerator::HTMLGenerator(const XML * xslSheet)
{
	this->treeTransformation(xslSheet);
}

/*
Method used to verify if a template contains the apply-template structure
*/
bool HTMLGenerator::isApplyTemplate(ElementXML * templ)
{
	vector<NodeXML *> *xslFils = templ->getChildren();
	if(xslFils->size()<=0 )
	{
		//If a template has no child nodes then we check if it contains the apply-template instruction
		return ((templ->getNameSpace().compare("xsl")==0) && (templ->getName().compare("apply-templates") ==0));
	}else
	{
		//Otherwise we use this function for all the child nodes after verifying that they are XML Elements
		for(int i=0; i < xslFils->size(); i++)
		{
			ElementXML* elemXML = dynamic_cast<ElementXML*>(xslFils->at(i));
			if(elemXML != NULL)
			{
				
				if(isApplyTemplate(elemXML))
				{
					return true;
				}
			}
			//free(elemXML);
		}	
	}
	return false;
}

//Method that that turns the xml file into HTML string
string HTMLGenerator::treeToHTML(NodeXML * root)
{
	string html ="";
	ElementXML* elemXML = dynamic_cast<ElementXML*>(root);
	if(elemXML != NULL)
	{
		
		ElementXML* templ= seekForTemplate(elemXML->getName());
		//If there is a matching template
		if(templ !=NULL)
		{
			//We check if we have to process the child nodes
			if(isApplyTemplate(elemXML))
			{
				vector<NodeXML *> * xmlFils = elemXML->getChildren();
				for(int i=0; i<xmlFils->size();i++)
				{
					treeToHTML(xmlFils->at(i));
				}
				
			}
			html += AssociateNodeTemplate(elemXML, templ);
		}else{
			//Otherwise we insert the text nodes of the current node without applying any tag
		}
	}else{
		return html;
	}
}

//Method that returns the matching xsl template for a given xml tag
ElementXML * HTMLGenerator::seekForTemplate(string name)
{
	NodeXML * xslTemplate = mapXsl.find(name)->second;

	ElementXML * element = dynamic_cast<ElementXML*>(xslTemplate);

	return element;
	
}

//Method used to fill a map with the templates contained in the xsl file
//the template is a map<name,ElementXML> where "name" is the name of the xml tag
void HTMLGenerator::treeTransformation(const XML * xslSheet)
{
	mapXsl.clear();
	ElementXML * rootXsl = xslSheet->getRoot();
	vector<NodeXML *> * children = rootXsl->getChildren();
	vector<NodeXML *>::iterator it = children->begin();
	
	//We process all the child nodes till we find : <xsl:template match="xxx">
	for ( ; it != children->end(); it++)
	{

		ElementXML* elemXSL = dynamic_cast<ElementXML*>((*it));
		
		if(elemXSL != NULL)
		{
			if (elemXSL->getNameSpace() == "xsl" && elemXSL->getName() == "template") 
			{
				
				vector<AttributeXML *> *  vectAtt = elemXSL->getAttributes();
				mapXsl.insert(pair<string, NodeXML *>((*vectAtt)[0]->getValue(), (*it)));
			}
		}

	}
}

string RemoveExternTags(string s)
{
	if ( (s.find("<") != string::npos) && (s.find(">") != string::npos) )
	{
	//remove the opening tag
	s.erase(0, s.find_first_of(">") + 1 );
	
	size_t last_closing = s.find_last_of(">");
        
        size_t last_opening = s.find_last_of("<");
        
	s.erase(last_opening, last_closing - last_opening + 1);
        } 
        return s;
}

string RemoveFirstTag(string s)
{
    //remove the opening tag
    size_t first_opening = s.find_first_of("<");
    size_t first_closing = s.find_first_of(">");
    s.erase(first_opening, first_closing - first_opening + 1 );

    return s;
}
/*Remove the text until the first tag( suppose that s begin with text)*/
string RemoveFirstText(string s)
{
	
	if ( (s.find("<") != string::npos) && (s.find(">") != string::npos) ) //There is a '<' and a '>'
		return s.erase(0, s.find_first_of("<")) ;
	else
		return "";
}


int CheckConformity(string str)/*Not ok*/
{
    size_t found;
    int nb;

    found = str.find_first_of("<>");
    while (found != string::npos)
    {
        nb++;
        found = str.find_first_of("<>",found++);
        cout << nb << endl;
    }
    
    return ((nb % 2 == 0) && nb > 0 ) ? nb : -1;
}


/**Check if the tag has to be added to the html file OK**/
bool addFirstTag(string s)
{
    if (s.substr(s.find_first_of("<"), s.find_first_of(">") + 1) == 
            "<xsl:apply-templates />" )
        cout << "gagné" << endl;
    else 
        cout << "perdu" << endl;
    return true;
}

/*returns the containt of the tag s OK*/
string BetweenTheFirstTag(string s)
{
    return(s.substr(s.find_first_of("<") + 1, s.find_first_of(">") -1));
}

/*Check if the balise is an xsl tag or not OK*/
bool IsAnXslTag(string s)
{
    string str = s.substr(s.find_first_of("<") + 1, s.find_first_of(">") -1);
    if (str.find("xsl:") != string::npos )//it's an xsl tag
        return true;
    else 
        return false;
}

/*Check if the string begin with a tag OK*/
bool BeginWithATag(string s)
{
    if (s[0] == '<')
        return true;
    else 
        return false;
}

string GetFirstTag(string s)
{
    return(s.substr(s.find_first_of("<"), s.find_first_of(">") + 1));
}

string GetTextToNextTag(string s)
{
    return s.substr(0, s.find_first_of('<'));
}
string getText(NodeXML * node)
{
	string result ="";
	ElementXML * element = dynamic_cast<ElementXML * >(node);
	if(element == NULL)
		cout <<" ca merde" <<endl;
	else{
		vector<NodeXML *> * children = element->getChildren();
		for(int i=0; i< children->size();i++)
		{
			TextXML * text = dynamic_cast<TextXML * >(children->at(i));
			if(text!=NULL)
				result += text->getContent();
		}
	}
	return result;
}
/*This function returns the string to write in the html file*/
string HTMLGenerator::AssociateNodeTemplate(NodeXML * node, NodeXML * _template)
{
	string s = _template->toString();
	string result = "";
	/*if (int nbTag = CheckConformity(s) == -1) 
	{
		cerr << "One or more characters '<' / '>' are in the string";
		return NULL; 
	}*/

	
	RemoveExternTags(s);

	while(s.size() !=0)
	{
            if (BeginWithATag(s))
            {
                string firstTag = GetFirstTag(s);    
		cout <<"AFFICHAGE DE FIRST TAG : " << firstTag << endl;
                if (IsAnXslTag(firstTag))
                {
                	if (firstTag.find("xsl:template", 0) != string::npos)
			{
				cout << "xsl:template" << endl;
			}
			else if (firstTag.find("xsl:apply-templates", 0) != string::npos)
			{
				cout << "xsl:apply-templates" << endl;
			}
			else if (firstTag.find("xsl:value-of", 0) != string::npos)
			{
				cout << "xsl:value-of" << endl;
				result += getText(node);
			}
                }
             
		else //Not an xsl tag
		{
			result += firstTag;
			cout << "Not an xsl tag" << endl;
		}
	
               s = RemoveFirstTag(s);    

		if (s.size() == 0 )
			break;

            }
            else //do not begin with a tag
            {
                
                //it is some text that we add to result
                result += GetTextToNextTag(s);
                s = RemoveFirstText(s);
		if (s.size() == 0 )
			break;
            }
        }
	cout << result << endl;
return result;
}
